package com.apps.java.javanote02;

import java.io.*;
import java.util.Properties;
import java.util.Set;

public class _23IO流_特殊操作流 {
    /**
     * 特殊操作流
     * 	一、标准输入输出流
     * 		1. System类中有两个静态的成员变量：
     * 			public static final InputStream in：标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源；
     * 			public static final PrintStream out：标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标；
     * 		2.自己实现键盘录入数据：
     * 			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     * 			写起来太麻烦，java提供了一个类实现键盘录入：Scanner sc = new Scanner(System.in);
     *
     * 		3.输出语句的本质：是一个标准的输出流
     * 			printSystem ps = System.out;
     * 			printSystem类有的方法，System.out都可以使用
     *
     * 	二、打印流分类和特点
     * 		分类：
     * 		（1）字节打印流：PrintStream
     * 			PrintStream(String fileName)：使用指定的文件名创建新的打印流
     * 			使用继承父类的方法写数据，查看的时候会转码；使用自己的特有方法写数据，查看的数据原样输出
     * 		（2）字符打印流：PrintWriter
     * 			构造方法：
     * 				方法名										说明
     * 				PrintWriter(String fileName)				使用指定的文件名创建一个新的PrintWriter，而不需要自动执行刷新
     * 				PrintWriter(Writer out,boolean autoFlush)	创建一个新的PrintWriter（out：字符输出流；autoFlush：一个布尔值，如果为真，则println、printf或format方法将刷新输出缓冲流）
     *
     * 		特点：
     * 		（1）只负责输出数据，不负责读取数据
     * 		（2）有自己特有方法
     *
     * 	三、Properties
     * 		1.概述：	（1）是一个Map体系的集合类
     * 				（2）Properties可以保存到流中或从流中加载
     *
     * 		2.Properties作为集合的特有方法：
     * 			方法名
     * 			（1）Object setProperty(String key,String value)
     * 				设置集合的键和值，都是String类型，底层调用Hashtable方法put
     * 			（2）String getProperty(String key)
     * 				使用此属性列表指定的键搜索属性
     * 			（3）Set<String> stringPropertyNames()
     * 				从该属性列表中返回一个不可修改的键集，其中键及其对应的值是字符串
     *
     * 		3.Properties和IO流结合的方法：
     * 			方法名
     * 			（1）void load(InputStream inStream)					从输入字节流读取属性列表(键和元素对)
     * 			（2）void load(Reader reader)							从输入字符流读取属性列表(键和元素对)
     * 			（3）void store(OutputStream out,String comments)		将此属性列表(键和元素对)写入此Properties表中，以适合于使用load(InputStream)方法的格式写入输出字节流
     * 			（4）void store(Writer writer,String comments)		将此属性列表(键和元素对)写入此Properties表中，以适合使用load(Reader)方法的格式写入输出字符流
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */
    public static void main(String[] args) throws IOException {

		/*
	//public static final InputStream in：标准输入流。
		InputStream is = System.in;

		//一次读取一个字节
		int by;
		while((by=is.read()) !=-1 ){
			System.out.print((char)by);
		}

	//如何把字节流转换为字符流？用转换流
		InputStreamReader isr = new InputStreamReader(is);
		//使用字符流能不能实现一次读取一行数据呢？可以
		//但是：一次读取一行数据的方法是字符缓冲输入流的特有方法
		BufferedReader br = new BufferedReader(isr);
		*/

		/*
	//创建字符缓冲输入流对象，并创建转换流转换字节流为字符流
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		System.out.println("请输入一个字符串：");
		//读取一行数据
		String line = br.readLine();
		System.out.println("你输入的字符串是：" + line);

		System.out.println("请输入一个整数:");
		int intline = Integer.parseInt(br.readLine());
		System.out.println("整数是：" + intline);

		//关闭资源
		br.close();

	//自己实现键盘录入太麻烦，所有java提供了一个类供我们使用：Scanner
		Scanner sc = new Scanner(System.in);
		*/

        //public static final PrintStream out：标准输出流。
        System.out.println("标准输出流的使用：");
        PrintStream ps = System.out;

        //方便的打印各种数据值
        ps.print("hello");//在控制台输出
        ps.print(100);

        ps.println("world");//在控制台输出并换行
        ps.println(200);

        //System.out的本质是一个字节输出流
        System.out.println("hello world");
        System.out.println(300);


        //字节打印流
        //PrintStream(String fileName)：使用指定的文件名创建新的打印流
        PrintStream pst = new PrintStream("i.txt");

        //写数据
        //字节输出流有的方法
        pst.write(98);

        //特有方法
        pst.println("aaa");
        pst.print(97);

        //释放资源
        pst.close();

        //字符打印流
        //PrintWriter(String fileName):使用指定的文件名创建一个新的PrintWriter，而不需要自动执行刷新
        PrintWriter pw = new PrintWriter("s.txt");

        //使用字符输出流有的方法
        pw.write("aaaccc");
        pw.flush();

        //特有方法
        pw.println("bbbccc");
		/*println相当于这两步动作
		 	pw.write("aaaccc");
			pw.flush();
		 */
        pw.flush();

        //PrintWriter(Writer out,boolean autoFlush)	创建一个新的PrintWriter（out：字符输出流；autoFlush：一个布尔值，如果为真，则println、printf或format方法将刷新输出缓冲流）
        PrintWriter pwt = new PrintWriter(pw, true);
        pwt.println("ooopppp");

        System.out.println("----------------------------");

        //properties作为集合使用
        System.out.println("properties作为集合使用：");
        //创建集合对象
        //Properties<String,String> pro = new Properties<>();//错误，properties不能泛型
        Properties prop = new Properties();

        //存储元素
        prop.put("1001", "赵丽颖");
        prop.put("1002", "杨幂");
        prop.put("1003", "迪丽热巴");

        //获取键值
        Set<Object> keySet = prop.keySet();
        //循环遍历
        for(Object key : keySet){
            Object value = prop.get(key);
            System.out.println(key + "," + value);
        }

        System.out.println("--------------------------");

        //properties作为集合的特有方法
        System.out.println("properties作为集合的特有方法：");

        //创建集合对象
        Properties pro = new Properties();

        //Object setProperty(String key,String value)设置集合的键和值，都是String类型，底层调用Hashtable方法put
        pro.setProperty("001", "Angelababy");
        pro.setProperty("002", "lisa");
        pro.setProperty("003", "jake");

        //控制台输出集合
        System.out.println(pro);

        //String getProperty(String key)使用此属性列表指定的键搜索属性
        System.out.println("使用此属性列表指定的键搜索属性：" + pro.getProperty("001"));

        //Set<String> stringPropertyNames()从该属性列表中返回一个不可修改的键集，其中键及其对应的值是字符串
        Set<String> names = pro.stringPropertyNames();
        for(String s : names){
            String value = pro.getProperty(s);
            System.out.println(s + "," + value);
        }

        System.out.println("--------------------------");

        //Properties结合IO流的使用
        //创建集合对象
        Properties pro2 = new Properties();

        //存储元素
        pro2.setProperty("dayunhan001", "彭于晏");
        pro2.setProperty("dayunhan002", "刘德华");
        pro2.setProperty("dayunhan002", "吴彦祖");

        //void store(OutputStream out,String comments)将此属性列表(键和元素对)写入此Properties表中，以适合于使用load(InputStream)方法的格式写入输出字节流
        pro2.store(new FileOutputStream("p.txt"), "helloworld");

        //void store(Writer writer,String comments)将此属性列表(键和元素对)写入此Properties表中，以适合使用load(Reader)方法的格式写入输出字符流
        pro2.store(new FileWriter("pro.txt"), "Proterties将属性列表写入文件");

        //void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
        pro2.load(new FileInputStream("s.txt"));
        System.out.println("从输入字节路读取属性列表：" + pro2);

        //void load(Reader reader)从输入字符流读取属性列表(键和元素对)
        pro2.load(new FileReader("i.txt"));
        System.out.println("从字符输入流读取属性列表：" + pro2);


    }
}
